#pragma once
/* Copyright (C) 2009 Vlad Roubtsov. All rights reserved. */

#include <boost/preprocessor/punctuation/comma_if.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>

#include "vr/exception/exceptions.hpp"
#include "vr/util/assertions.hpp"

//----------------------------------------------------------------------------
namespace vr
{
namespace deject
{
namespace factory
{

template<typename T, int ac>
struct constructor_adaptor
{
    static inline
    deject::component_base * create (const deject::component_id_type & ID, const ptr_vector<dependency> & args)
    {
        __VR_THROW_X (std::domain_error, "no component_factory constructor adaptor specified for [" + ID + "]");
    }
};

template<typename T>
struct constructor_adaptor<T, 0>
{
    static inline
    deject::component_base * create (const deject::component_id_type & ID, const ptr_vector<dependency> & args)
    {
        VR_SASSERT (args.empty ());
        return new T (ID);
    }
};

#define __VR_ARG(unused, i, name) BOOST_PP_COMMA_IF(i) name [ i ]
#define __VR_ARG_LIST(length) BOOST_PP_REPEAT(length, __VR_ARG, args)

#define __VR_SPECIALIZE_FOR_ARG_COUNT(ac) \
    template<typename T>\
    struct constructor_adaptor< T, ac >\
    {\
        static inline\
        deject::component_base * create (const deject::component_id_type & ID, const ptr_vector<dependency> & args)\
        {\
            VR_SASSERT (args.size () == ac);\
            return new T (ID, __VR_ARG_LIST(ac) );\
        }\
    };

    __VR_SPECIALIZE_FOR_ARG_COUNT (1)
    __VR_SPECIALIZE_FOR_ARG_COUNT (2)
    __VR_SPECIALIZE_FOR_ARG_COUNT (3)
    __VR_SPECIALIZE_FOR_ARG_COUNT (4)
    __VR_SPECIALIZE_FOR_ARG_COUNT (5)
    __VR_SPECIALIZE_FOR_ARG_COUNT (6)
    __VR_SPECIALIZE_FOR_ARG_COUNT (7)
    __VR_SPECIALIZE_FOR_ARG_COUNT (8)

#undef __VR_SPECIALIZE_FOR_ARG_COUNT

#undef __VR_ARG_LIST
#undef __VR_ARG

} // end of 'factory'
} // end of 'deject'
} // end of namespace
//----------------------------------------------------------------------------
